package com.wrt.sps.mgt.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.wrt.sps.mgt.dao.UserDao;
import com.wrt.sps.mgt.entity.Role;
import com.wrt.sps.mgt.entity.User;
import com.wrt.sps.mgt.pojo.UserDTO;
import com.wrt.sps.mgt.pojo.UserQueryDTO;
import com.wrt.sps.mgt.service.RoleService;
import com.wrt.sps.mgt.service.UserService;

/**
 * 用户管理服务实现层
 * 
 * @author 文瑞涛
 * @date 2020年12月13日 下午2:45:13
 */
@Service
public class UserServiceImpl implements UserService {

	@Resource
	private RoleService roleService;
	@Resource
	private UserDao userDao;

	@Override
	@PostConstruct
	@Transactional(rollbackFor = Exception.class)
	public void initAdminUser() {
		User adminUser = findUserByLoginName("admin");
		if (null == adminUser) {
			adminUser = new User();
			adminUser.createAdmin();
			Role adminRole = new Role();
			adminRole.createAdminRole();
			adminUser.setRole(roleService.findRoleByExample(adminRole));
			userDao.save(adminUser);
		}
	}

	@Override
	@Transactional(readOnly = true)
	public User findUserByLoginName(String loginName) {
		return userDao.findUserByLoginName(loginName);
	}

	@Override
	@Transactional(readOnly = true)
	public User findUserById(Long id) {
		Optional<User> temp = userDao.findById(id);
		if (temp.isPresent()) {
			return temp.get();
		}
		return null;
	}

	@Override
	@Transactional(readOnly = true)
	public Page<User> query(UserQueryDTO dto, int page, int limit) {
		Pageable pageable = PageRequest.of(page, limit, Sort.by(Sort.Direction.DESC, "createdDate", "id"));
		User queryUser = new User();
		queryUser.setLoginName(dto.getLoginName());
		queryUser.setValidFlag(dto.getValidFlag() != null ? dto.getValidFlag().booleanValue() : Boolean.TRUE);
		ExampleMatcher matcher = ExampleMatcher.matching()
				.withMatcher("loginName", GenericPropertyMatchers.contains().ignoreCase())
				.withMatcher("isValidFlag", GenericPropertyMatchers.storeDefaultMatching()).withIgnorePaths("password");
		Example<User> example = Example.of(queryUser, matcher);
		return userDao.findAll(example, pageable);
	}

	@Override
	@Transactional(readOnly = true)
	public List<Long> countUsers() {
		List<Long> result = new ArrayList<>();
		result.add(userDao.count());
		User queryUser = new User();
		queryUser.setValidFlag(true);
		result.add(userDao.count(Example.of(queryUser)));
		queryUser.setValidFlag(false);
		result.add(userDao.count(Example.of(queryUser)));
		return result;
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public User save(UserDTO dto) {
		User saveUser = null;
		if (null != dto.getKey() && 0 != dto.getKey()) {
			Optional<User> temp = userDao.findById(dto.getKey());
			if (temp.isPresent()) {
				saveUser = temp.get();
			} else {
				return null;
			}
		} else {
			saveUser = new User();
			saveUser.setLoginName(dto.getLoginName());
			saveUser.setPassword(dto.getPassword());
		}
		saveUser.setValidFlag(dto.getValidFlag());
		if (null != dto.getRoleId() && 0 != dto.getRoleId()) {
			saveUser.setRole(roleService.findRoleById(dto.getRoleId()));
		}
		return userDao.save(saveUser);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delete(Long id) {
		Optional<User> temp = userDao.findById(id);
		if (temp.isPresent() && !temp.get().getValidFlag().booleanValue()) {
			userDao.deleteById(id);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public User save(User user) {
		return userDao.saveAndFlush(user);
	}
}
